<?php
use think\facade\Db;

use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use think\exception\ValidateException;
use think\facade\Filesystem;
include_once '../vendor/aliyun-green/aliyuncs/aliyun-php-sdk-core/Config.php';
use Green\Request\V20180509 as Green;
// 应用公共文件


    function get_csv_data ($file_path)
    {
        $fp = fopen($file_path, 'r');

        $data = [];
        // 逐行输出文件内容
        while($line = fgetcsv($fp)){
            array_push($data, $line);
        }

        // 文件关闭
        fclose($fp);

        return $data;
    }

    // 文本检测
    function textDetection($data)
    {
        foreach ($data as &$v) {
            if (!is_array($v)) {
                if (!empty($v)) {
                    $res = textSync($v);
                    if ($res['code'] == 500) {
                        return $res['msg'];
                    }
                }
            }
        }
        return '';
    }

    /**
     * 文字鉴黄（垃圾文本检测）
     * @date: 2019年6月10日
     * @author: Administrator
     * @return:
     */
    function textSync($text='')
    {
        $accessKeyId = 'LTAIflf5ziysBMyJ';
        $accessKeySecret = 'yeqVHlqdZC4OqLl04KkgdUa02zvoxJ';
        if (!$text) {
            return ['code'=>500,'data'=>[],'msg'=>'请输入内容'];
        }
        $ak = [
            'accessKeyId' => $accessKeyId,
            'accessKeySecret' => $accessKeySecret
        ];
        //请替换成你自己的accessKeyId、accessKeySecret
        $iClientProfile = \DefaultProfile::getProfile("cn-shanghai", $ak["accessKeyId"], $ak["accessKeySecret"]); // TODO
        \DefaultProfile::addEndpoint("cn-shanghai", "cn-shanghai", "Green", "green.cn-shanghai.aliyuncs.com");
        $client = new \DefaultAcsClient($iClientProfile);

        $request = new Green\TextScanRequest();
        $request->setMethod("POST");
        $request->setAcceptFormat("JSON");

        $task1 = array('dataId' =>  uniqid(),
            'content' => $text
        );
        $request->setContent(json_encode(array("tasks" => array($task1),
            "scenes" => array("antispam"))));

        try {
            $response = $client->getAcsResponse($request);
            if(200 == $response['code']){
                $taskResults = $response['data'];
                foreach ($taskResults as $taskResult) {
                    if (200 == $taskResult['code']) {
                        $sceneResults = $taskResult['results'];
                        foreach ($sceneResults as $sceneResult) {
                            $scene = $sceneResult['label'];
                            $suggestion = $sceneResult['suggestion'];
                            //根据scene和suggetion做相关的处理
                            //do something
                            if ($suggestion != 'pass') {
                                $arr = [
                                    'normal'=> '正常文本',
                                    'spam'=> '含垃圾信息',
                                    'ad'=> '广告',
                                    'politics'=> '涉政',
                                    'terrorism'=> '暴恐',
                                    'abuse'=> '辱骂',
                                    'porn'=> '色情',
                                    'flood'=> '灌水',
                                    'contraband'=> '违禁',
                                    'meaningless'=> '无意义',
                                    'customized'=> '自定义关键词',
                                ];
                                return ['code'=>500,'data'=>[],'msg'=>'内容含有【'.$arr[$scene].'】内容, 请修改后重新提交'];
                            }
                        }
                    } else {
                        return ['code'=>500,'data'=>[],'msg'=>"请求失败1:" + $response['code']];
                    }
                }

                //正常
                return (['code'=>200,'data'=>[],'msg'=>'']);
            } else {
                return ['code'=>500,'data'=>[],'msg'=>"请求失败2:" . $response['code']];
            }

        } catch (\Exception $e) {
            $code = $e->getCode();
            $error_message = $e->getMessage();
            return ['code'=>500,'data'=>[],'msg'=>$code.": ".$error_message];
        }

    }

    function http_get($url){
        $oCurl = curl_init();
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        //dump($sContent);
        curl_close($oCurl);
        if(intval($aStatus["http_code"])==200){
            return $sContent;
        }else{
            return false;
        }
    }

    /**
     * POST 请求
     * @param string $url
     * @param array $param
     * @param boolean $post_file 是否文件上传
     * @return string content
     */
    function http_post($url,$param,$post_file=false, $header=[])
    {
        $oCurl = curl_init();
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (is_string($param) || $post_file) {
            $strPOST = $param;
        } else {
            $aPOST = array();
            foreach($param as $key=>$val){
                $aPOST[] = $key."=".urlencode($val);
            }
            $strPOST =  join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
        if (!empty($header)) {
            curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($oCurl, CURLOPT_POST,true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        return $sContent;
    }



    function dedao_post($url,$param,$post_file=false, $header){
        $oCurl = curl_init();
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (is_string($param) || $post_file) {
            $strPOST = $param;
        } else {
            $aPOST = array();
            foreach($param as $key=>$val){
                $aPOST[] = $key."=".urlencode($val);
            }
            $strPOST =  join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt($oCurl, CURLOPT_POST,true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header); // header头里添加参数
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        return $sContent;
    }

    function dedao_get($url, $arr){
        $oCurl = curl_init();
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );

        curl_setopt($oCurl, CURLOPT_HTTPHEADER, $arr); // header头里添加参数
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        return $sContent;
    }


    /**
     * POST 请求
     * @param string $url
     * @param array $param
     * @param boolean $post_file 是否文件上传
     * @return string content
     */
    function zhibo_http_post($url,$param,$post_file=false, $header=[]){
        $oCurl = curl_init();
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (is_string($param) || $post_file) {
            $strPOST = $param;
        } else {
            $aPOST = array();
            foreach($param as $key=>$val){
                $aPOST[] = $key."=".urlencode($val);
            }
            $strPOST =  join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
        if (!empty($header)) {
            curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($oCurl, CURLOPT_POST,true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        return $sContent;
    }

    function zhibo_http_get($url){
        $oCurl = curl_init();
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        return $sContent;
    }

    function request_post($url, $param, $post_file=false, $header)
    {
        $oCurl = curl_init();
        if (stripos($url,"https://")!==FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (is_string($param) || $post_file) {
            $strPOST = $param;
        } else {
            $aPOST = array();
            foreach($param as $key=>$val){
                $aPOST[] = $key."=".urlencode($val);
            }
            $strPOST =  join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt($oCurl, CURLOPT_POST,true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header); // header头里添加参数
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        return $sContent;
    }

    function request_get($url, $arr)
    {
        $oCurl = curl_init();
        if (stripos($url,"https://")!==FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );

        curl_setopt($oCurl, CURLOPT_HTTPHEADER, $arr); // header头里添加参数
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        return $sContent;
    }

    //+检查权限
    function check_jurisdiction($role_id = null, $control, $action)
    {
        $date = date('Ymd', time());
        $file_path = root_path() . "/public/log/".$date.".txt";

        $fp = fopen($file_path,'a');

        //添加BOM头，以UTF8编码导出CSV文件，如果文件头未添加BOM头，打开会出现乱码。
        fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));

        $where = [];
        $where[] = ['control', '=', $control];
        $where[] = ['action', '=', $action];

        $menu = Db::name('admin_menu')->where($where)->field('id, title')->find();

        fwrite($fp, session('admin_auth.givenname').' '.session('admin_auth.surname').'--'.$control.'/'.$action.'--'.$menu['title'].'--'.date('Y-m-d H:i:s', time())."\n");

        if (!is_admin()) {
            $role_id = is_null($role_id) ? session('admin_auth.role_id') : $role_id;
            $rule = Db::name('admin_role')->where(['id'=>$role_id])->find();

            if (in_array($menu['id'], explode(',', $rule['rule']))) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }

    //+检查权限
    function check_jurisdiction1($role_id = null, $control)
    {
        if (!is_admin()) {
            $where = [];
            $where[] = ['control', '=', $control];

            $menu = Db::name('admin_menu')->where($where)->field('id, title')->find();
            $role_id = is_null($role_id) ? session('admin_auth.role_id') : $role_id;
            $rule = Db::name('admin_role')->where(['id'=>$role_id])->find();

            if (in_array($menu['id'], explode(',', $rule['rule']))) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }

    function is_admin($id = null)
    {
        $id = is_null($id) ? session('admin_auth.id') : $id;
        $admin = Db::name('admin_user')->where(['id'=>$id,'status'=>1,'role_id'=>1])->find();
        if ($admin) {
            return true;
        }else{
            return false;
        }
    }



    function getTree($data)
    {//数组
        $items = [];
        foreach ($data as $v){
            $items[$v['id']] = $v; // $items[1] =
        }
        $tree = array(); //格式化好的树
        foreach ($items as $item)
            if (isset($items[$item['pid']]))
                $items[$item['pid']]['children'][] = &$items[$item['id']];
            else
                $tree[] = &$items[$item['id']];
        return $tree;
    }


    function getTree2($arr, $id = 'id', $fid = 'fid', $child_name = 'children')
    {
        $refer = array();
        $tree = array();
        foreach ($arr as $k => $v) {
            $refer[$v[$id]] = &$arr[$k]; //创建主键的数组引用
        }
        foreach ($arr as $k => $v) {
            $pid = $v[$fid]; //获取当前分类的父级id
            if ($pid == 1) {
                $tree[] = &$arr[$k]; //顶级栏目
            } else {
                if (isset($refer[$pid])) {
                    $refer[$pid][$child_name][] = &$arr[$k]; //如果存在父级栏目，则添加进父级栏目的子栏目数组中
                }
            }
        }
        return $tree;
    }


    /**
     * 获取所有子部门
     * @date: 2019年7月22日
     * @author: Administrator
     * @return:
     */
    function get_children($pid=0){

        $data = Db::name('branch')->where('pid', '=', $pid)->column('id');
        foreach ($data as $key => $value){
            $data1 = get_children($value);
            $data = array_merge($data, $data1);
        }
        return $data;
    }

    /**
     * 整理菜单住方法
     * @param $param
     * @return array
     */
    function prepareMenu($param)
    {

        $parent = []; //父类
        $child = [];  //子类

        foreach($param as $key=>$vo){
            if($vo['menu_id'] == 0){
                $vo['href'] = '';
                $parent[] = $vo;

            }else{
                $vo['href'] = (string)url($vo['control'] .'/'. $vo['action']);
                $child[] = $vo;
            }
        }

        foreach($parent as $key=>$vo){
            foreach($child as $k=>$v){
                if($v['menu_id'] == $vo['id']){
                    $parent[$key]['children'][] = $v;
                }
            }
        }

        return $parent;
    }


    function pre()
    {
        $exit = true;

        if(!$length = func_num_args()) {
            exit;
        }

        $args = func_get_args();

        if($length > 1) {
            if($args[ $length-1 ] === false) {
                $exit = false;
                array_pop($args);
            }
        }

        header('Content-Type: text/html; charset=utf8');

        echo '<pre>';
        foreach ($args as $i => $r) {
            if($i > 0) {
                echo '<br>'.str_repeat('- ', 10).'<br>';
            }
            print_r($r);
        }
        echo '</pre>';

        if($exit === true) {
            exit;
        }
    }



    /**
     * 读取配置文件
     * @param string $filename                  读取的配置文件
     * @param string $name                      获得某一项配置
     * @param mixed $default                    默认值
     * @uses confile('site.conf');              获得所有数据
     * @uses confile('site.conf', 'sitename');  获得某一项数据
     * @return mixed
     */
    function confile($filename, $name='', $default=array())
    {
        static $_data = array();

        $pathname = CONFILE_PATH . $filename . '.php';

        if(!isset($_data[$filename])) {
            if(is_file($pathname)) {
                $_data[$filename] = require $pathname;
            } else {
                $_data[$filename] = array();
            }
        }

        //+ 返回所有文件数据
        if($name === '') {
            return $_data[$filename] ? $_data[$filename] : $default;
        }

        return isset($_data[$filename][$name]) ? $_data[$filename][$name] : $default;
    }

    /**
     * 带有效期的加密解密
     * @param $string 加密/解密的字符串
     * @param string $operation   类型，E 加密；D 解密
     * @param string $key    密匙
     * @param int $expiry    有效期 单位秒，空则为永久
     * @return string
     */
    function temporaryEncrypt($string, $operation = 'D', $key = 'xzjyencrypt', $expiry = 0)
    {
        // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
        $ckey_length = 4;
        // 密匙
        $key = md5($key);

        // 密匙a会参与加解密
        $keya = md5(substr($key, 0, 16));
        // 密匙b会用来做数据完整性验证
        $keyb = md5(substr($key, 16, 16));
        // 密匙c用于变化生成的密文
        $keyc = $ckey_length ? ($operation == 'D' ? substr($string, 0, $ckey_length) :
            substr(md5($key), -$ckey_length)) : '';

        // 参与运算的密匙
        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);

        // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，
        //解密时会通过这个密匙验证数据完整性
        // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
        $string = $operation == 'D' ? base64_decode(substr($string, $ckey_length)) :
            sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;

        $string_length = strlen($string);
        $result = '';
        $box = range(0, 255);
        $rndkey = array();
        // 产生密匙簿
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }
        // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }
        // 核心加解密部分
        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            // 从密匙簿得出密匙进行异或，再转成字符
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }

        if ($operation == 'D') {
            // 验证数据有效性，请看未加密明文的格式
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) &&
                substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)
            ) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
            // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
            return $keyc . str_replace('=', '', base64_encode($result));
        }
    }


    /**
     * 生成指定长度随机字符串
     * @param number $length 随机串长度
     * $param boolean $only_number 只有数字
     * @return string
     */
    function create_rand_string($length=0, $only_number=false)
    {

        if($length === 0) {
            $length = rand(10, 30);
        }

        $letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

        $numbers = '0123456789';

        if($only_number === false) {
            $letters .= $numbers;
        } else {
            $letters = $numbers;
        }

        $str = '';
        $letterLength = strlen($letters);
        for($i=0; $i<$length; $i++) {
            $str .= $letters[ mt_rand(0, $letterLength-1) ];
        }
        return $str;
    }

    function remove_xss($arr)
    {
        $rows = [];
        foreach ($arr as $k => $v) {
            $rows[$k] = string_remove_xss(html_entity_decode($v));
        }

        return $rows;
    }



    //------------------------------php防注入和XSS攻击通用过滤-----Start--------------------------------------------//
    function string_remove_xss($html)
    {
        preg_match_all("/\<([^\<]+)\>/is", $html, $ms);

        $searchs[] = '<';
        $replaces[] = '&lt;';
        $searchs[] = '>';
        $replaces[] = '&gt;';

        if ($ms[1]) {
            $allowtags = 'img|a|font|div|table|tbody|caption|tr|td|th|br|p|b|strong|i|u|em|span|ol|ul|li|blockquote';
            $ms[1] = array_unique($ms[1]);
            foreach ($ms[1] as $value) {
                $searchs[] = "&lt;".$value."&gt;";

                $value = str_replace('&amp;', '_uch_tmp_str_', $value);
                $value = string_htmlspecialchars($value);
                $value = str_replace('_uch_tmp_str_', '&amp;', $value);

                $value = str_replace(array('\\', '/*'), array('.', '/.'), $value);
                $skipkeys = array('onabort','onactivate','onafterprint','onafterupdate','onbeforeactivate','onbeforecopy','onbeforecut','onbeforedeactivate',
                    'onbeforeeditfocus','onbeforepaste','onbeforeprint','onbeforeunload','onbeforeupdate','onblur','onbounce','oncellchange','onchange',
                    'onclick','oncontextmenu','oncontrolselect','oncopy','oncut','ondataavailable','ondatasetchanged','ondatasetcomplete','ondblclick',
                    'ondeactivate','ondrag','ondragend','ondragenter','ondragleave','ondragover','ondragstart','ondrop','onerror','onerrorupdate',
                    'onfilterchange','onfinish','onfocus','onfocusin','onfocusout','onhelp','onkeydown','onkeypress','onkeyup','onlayoutcomplete',
                    'onload','onlosecapture','onmousedown','onmouseenter','onmouseleave','onmousemove','onmouseout','onmouseover','onmouseup','onmousewheel',
                    'onmove','onmoveend','onmovestart','onpaste','onpropertychange','onreadystatechange','onreset','onresize','onresizeend','onresizestart',
                    'onrowenter','onrowexit','onrowsdelete','onrowsinserted','onscroll','onselect','onselectionchange','onselectstart','onstart','onstop',
                    'onsubmit','onunload','javascript','script','eval','behaviour','expression','style','class','onerror','confirm',  'prompt','link','xml','select','insert','update','delete','blink','meta','body','tag','alert','input','iframe','html','js','css','php','http-equiv','console');
                $skipstr = implode('|', $skipkeys);
                $value = preg_replace(array("/($skipstr)/i"), '.', $value);
                if (!preg_match("/^[\/|\s]?($allowtags)(\s+|$)/is", $value)) {
                    $value = '';
                }
                $replaces[] = empty($value) ? '' : "<" . str_replace('&quot;', '"', $value) . ">";
            }
        }
        $html = str_replace($searchs, $replaces, $html);

        return $html;
    }


    //php防注入和XSS攻击通用过滤
    function string_htmlspecialchars($string, $flags = null)
    {
        if (is_array($string)) {
            foreach ($string as $key => $val) {
                $string[$key] = string_htmlspecialchars($val, $flags);
            }
        } else {
            if ($flags === null) {
                $string = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $string);
                if (strpos($string, '&amp;#') !== false) {
                    $string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
                }
            } else {
                if (PHP_VERSION < '5.4.0') {
                    $string = htmlspecialchars($string, $flags);
                } else {
                    if (!defined('CHARSET') || (strtolower(CHARSET) == 'utf-8')) {
                        $charset = 'UTF-8';
                    } else {
                        $charset = 'ISO-8859-1';
                    }
                    $string = htmlspecialchars($string, $flags, $charset);
                }
            }
        }

        return $string;
    }

    //------------------php防注入和XSS攻击通用过滤-----End--------------------------------------------//



    /**
     * 加密方法
     * @param string $str
     * @return string
     */
    function encrypts($str)
    {
        return base64_encode(openssl_encrypt($str, "aes-256-cbc", '12f862d21d3ceafba1b88e5f22960d55', true, '0000000000000000'));
    }



    /**
     * 解密方法
     * @param string $str
     * @return string
     */
    function decrypts($str)
    {
        $decryptStr = openssl_decrypt(base64_decode($str), "aes-256-cbc", '12f862d21d3ceafba1b88e5f22960d55', OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, '0000000000000000');
        $sArray = str_split($decryptStr);
        //可能由于语言问题，.net生成的加密密文解密后，最右有空白字符，但不是空格，遂将其转为ascii后删除32（含）以下的字符
        foreach ($sArray as $item) {
            $assii = ord($item);
            if ($assii <= 32) {
                $decryptStr = str_replace(chr($assii), "", $decryptStr); //删除此ASCII字符
            }
        }
        return $decryptStr;
    }



    function msecdate($time)
    {
        $tag='Y-m-d H:i:s';
        $a = substr($time,0,10);
        $b = substr($time,10);
        $date = date($tag,$a).'.'.$b;
        return $date;
    }


    // 获取轻学堂个人总学习数据
    function get_stat_data_by_open_ids($userid, $start='', $end='')
    {
        if (empty($start) && empty($end)) {
            $string = "appId=".config('app.school.appid')."&authCorpId=".config('app.school.auth_corpid')."&openIds=".json_encode(array(encrypts($userid)))."&appSecret=".config('app.school.secret');
        } else {
            $string = "appId=".config('app.school.appid')."&authCorpId=".config('app.school.auth_corpid')."&endDate=".$end."&openIds=".json_encode(array(encrypts($userid)))."&startDate=".$start."&appSecret=".config('app.school.secret');
        }


        $sign = strtoupper(md5($string));
        $url = "https://www.qingxuetang.com/open/api/corpData/getStatDataByOpenIds";
        $arr = array(
            'appId'         => config('app.school.appid'),
            'authCorpId'    => config('app.school.auth_corpid'),
            'openIds'        => json_encode(array(encrypts($userid))),
            'sign'          => $sign
        );
        if (!empty($start) && !empty($end)) {
            $arr['endDate'] = $end;
            $arr['startDate'] = $start;
        }
        $res = json_decode(http_post($url, $arr),true);
        return $res;
    }



// 获取个人轻学堂课程数据
    function get_user_learnt_courses($userid, $start='', $end='')
    {
        $data = [];
        for ($i = 0; $i <= 1000; $i+=100) {
            $count = 100;
            //+获取学习记录
            if (empty($start) && empty($end)) {
                $string = "appId=".config('app.school.appid')."&authCorpId=".config('app.school.auth_corpid')."&count=".$count."&offset=".$i."&openId=".encrypts($userid)."&appSecret=".config('app.school.secret');
            } else {
                $string = "appId=".config('app.school.appid')."&authCorpId=".config('app.school.auth_corpid')."&count=".$count."&endDate=".$end."&offset=".$i."&openId=".encrypts($userid)."&startDate=".$start."&appSecret=".config('app.school.secret');
            }
            $sign = strtoupper(md5($string));
            $url = "https://www.qingxuetang.com/open/api/corpData/getUserLearntCourses";
            $arr = array(
                'appId'         => config('app.school.appid'),
                'authCorpId'    => config('app.school.auth_corpid'),
                'count'         => $count,
                'offset'        => $i,
                'openId'        => encrypts($userid),
                'sign'          => $sign
            );
            if (!empty($start) && !empty($end)) {
                $arr['endDate'] = $end;
                $arr['startDate'] = $start;
            }
            $res = json_decode(http_post($url, $arr),true);
            if ($res['ret'] == 0) {
                if (!empty($res['data'])) {
                    $info = $res['data']['dataList'];
                    if (empty($res['data']['dataList'])) {
                        break;
                    } else {
                        foreach ($info as &$val) {
                            array_push($data, $val);
                        }
                    }
                } else {
                    break;
                }
            } else {
                break;
            }
        }

        return $data;
    }

    // 获取得到个人总学习数据
    function get_dedao_total($openid)
    {
        $time = time();
        $nonce = create_rand_string(32);
        $datas = [
            '/qy/v1/stat/date/list',
            'GET',
            'outer_id='.$openid.'&start_date=2020-06-10&end_date='.date('Y-m-d', time()),
            '',
            '',
            $time,
            $nonce,
        ];
        $signValue = implode("\n", $datas);
        $sign = base64_encode(hash_hmac('sha256', $signValue, config('app.dedao.sk'), true));

        $url = config('dedao.url').'/qy/v1/stat/date/list?outer_id='.$openid.'&start_date=2020-06-10&end_date='.date('Y-m-d', time());
        $header = [
            "G-Auth-Appid: ".config('app.dedao.ak'),
            "G-Auth-Sign: $sign",
            "G-Auth-Identity: ".config('app.dedao.identity'),
            "G-Auth-Ts: $time",
            "G-Auth-Nonce: $nonce",
            "G-Auth-Method: HmacSHA256"
        ];
        $res = json_decode(dedao_get($url, $header), true);
        return $res;
    }

    function get_user_attr($user,$name)
    {
        foreach ($user['extattr']['attrs'] as $key => $value) {
            if ($name == $value['name']) {
                return $value['value'];
            }
        }
    }


    // 读取excel表格
    function get_excel_info($filename)
    {
        set_time_limit(0);
        try {
            // 截取后缀
            $fileExtendName = substr(strrchr($filename, '.'), 1);

            // 有Xls和Xlsx格式两种
            if ($fileExtendName == 'xlsx') {
                $objReader = IOFactory::createReader('Xlsx');
            } else {
                $objReader = IOFactory::createReader('Xls');
            }

            // 设置文件为只读
            $objReader->setReadDataOnly(TRUE);

            // 读取文件，tp6默认上传的文件，在runtime的相应目录下，可根据实际情况自己更改
            $objPHPExcel = $objReader->load(runtime_path() . 'storage/' . $filename);

            //excel中的第一张sheet
            $sheet = $objPHPExcel->getSheet(0);

            // 取得总行数
            $highestRow = $sheet->getHighestRow();

            // 取得总列数
            $highestColumn = $sheet->getHighestColumn();

            Coordinate::columnIndexFromString($highestColumn);

            $lines = $highestRow - 1;
            if ($lines <= 0) {
                return [
                    'data' => [],
                    'code' => 1,
                    'msg' => '未读取到数据'
                ];
            }


            // 直接取出excle中的数据
            $data = $objPHPExcel->getActiveSheet()->toArray();

            // 删除第一个元素（表头）
            array_shift($data);

            //删除文件
            unlink(runtime_path() . 'storage/' . $filename);

            // 返回结果
            return [
                'data' => $data,
                'code' => 0,
                'msg' => ''
            ];
        } catch (\Exception $e) {
            return [
                'data' => [],
                'code' => 1,
                'msg' => $e->getMessage()
            ];
        }
    }

    /**
     * 获取指定日期之间的各个月
     */
    function get_months($sdate, $edate)
    {
        $sdateTemp = $sdate;
        $edateTemp = $edate;

        $range_arr = array();
        do {
            $monthinfo = get_monthinfo_by_date($sdate);
            $end_day = $monthinfo['month_end_day'];
            $start = substr_date($monthinfo['month_start_day']);//月起始日期
            $end = substr_date($monthinfo['month_end_day']);//月结束日期


            if($start<$sdateTemp) $start = $sdateTemp;
            if($end>$edateTemp) $end = $edateTemp;

            $range = "{$start} ~ {$end}";
            $range_arr[] = $range;
            $sdate = date('Y-m-d', strtotime($sdate.'+1 month'));
        }while($end_day < $edate);

        return $range_arr;
    }


    /**
     * 根据指定日期获取所在月的起始时间和结束时间
     */
    function get_monthinfo_by_date($date)
    {
        $ret = array();
        $timestamp = strtotime($date);
        $mdays = date('t', $timestamp);

        return array(
            'month_start_day' => date('Y-m-1', $timestamp),
            'month_end_day' => date('Y-m-'.$mdays, $timestamp)
        );
    }

    /**
     * 截取日期中的月份和日
     * @param string $date
     * @return string $date
     */
    function substr_date($date)
    {
        if ( ! $date) return FALSE;
        return date('Y-m-d', strtotime($date));
    }

    /**
     * 获取指定日期范围内的时间
     */
    function get_date($start, $end) {
        $arr = [];
        for($i=0;strtotime($start.'+'.$i.' days')<=strtotime($end)&&$i<365;$i++){
            $time = strtotime($start.'+'.$i.' days');
            $arr[$i] = date('Y/m/d',$time);
        }

        return $arr;
    }

    /**
     * @name 排序 按照数组的某个字段值排序
     * @param $array 排序数组 $field 排序字段 $direction 排序顺序
     * @author wanglisong@aldwx.com
     * @date 2017-03-09
     */
     function sort_array($array,$field,$direction) {

        if($direction == 'desc') {
            $direction = 'SORT_DESC';
        }
        if($direction == 'asc') {
            $direction = 'SORT_ASC';
        }
        $sort = array(
            'direction' => $direction, //排序顺序标志 SORT_DESC 降序；SORT_ASC 升序
            'field' => $field, //排序字段
        );
        $arrSort = array();
        foreach($array as $key => $value) {
            foreach($value as $k => $v) {
                $arrSort[$k][$key] = $v;
            }
        }

        if($sort['direction']){
            array_multisort($arrSort[$sort['field']], constant($sort['direction']), $array);
        }
        return $array;
     }

     function get_se_to_time($times){
        $result = '00:00:00';
        if ($times > 0) {
            $hour = floor($times/3600);
            $minute = floor(($times-3600 * $hour)/60);
            $second = floor((($times-3600 * $hour) - 60 * $minute) % 60);
            $result = $hour.':'.$minute.':'.$second;
        }
        return $result;
    }


    /**
     * 友好显示时间
     */
    function formatdate($time = null)
    {
        $text = '';
        $time = $time === null || $time > time() ? time() : intval($time);
        $t    = time() - $time;

        //时间差 （秒）
        if ($t == 0) {
            $text = '刚刚';
        } elseif ($t < 60) {
            $text = $t . '秒前';
        }

        // 一分钟内
        elseif ($t < 60 * 60) {
            $text = floor($t / 60) . '分钟前';
        }

        //一小时内
        elseif ($t < 60 * 60 * 24) {
            $text = floor($t / (60 * 60)) . '小时前';
        }

        //昨天和前天
        elseif ($t < 60 * 60 * 24 * 30) {
            $text = date('m月d日 H:i', $time);
        }

        //一个月内
        elseif ($t < 60 * 60 * 24 * 365) {
            $text = date('m月d日', $time);
        }

        //一年内
        else {
            $text = date('Y年m月d日', $time);
        }

        //一年以前
        return $text;
    }


    // 获取表信息
    function get_info($id, $table = 'Category', $field = 'title', $isall = false)
    {
        if (!$id || !$table) {
            return '';
        } else {
            if ($field) {
                $info = Db::name($table)->field($field)->find($id);
                if (!$isall) {
                    $info = isset($info[$field]) ? $info[$field] : [];
                }
            } else {
                $info = Db::name($table)->find($id);
            }
            if (!$info) {
                return '';
            } else {
                return $info;
            }

        }
    }

    function get_config($name,$id){
        if ($name && $id) {
            $arr = config($name);
            return $arr[$id];
        } else {
            if ($name == 'app.course.english') {
                $arr = config($name);
                $id = intval($id);
                return $arr[$id];
            }else{
                return '';
            }
        }
    }


    function get_sec_to_time($time){
        if(is_numeric($time)){
            $value = array(
                "hours" => 0,
                "minutes" => 0, "seconds" => 0,
            );
            if($time >= 3600){
                $value["hours"] = floor($time/3600);
                $time = ($time%3600);
            }
            if($time >= 60){
                $value["minutes"] = floor($time/60);
                $time = ($time%60);
            }
            $value["seconds"] = floor($time);
            if (strlen($value["hours"]) == 1) {
                $value["hours"] = '0'.$value["hours"];
            }
            if (strlen($value["minutes"]) == 1) {
                $value["minutes"] = '0'.$value["minutes"];
            }
            if (strlen($value["seconds"]) == 1) {
                $value["seconds"] = '0'.$value["seconds"];
            }
            $t = $value["hours"] .":". $value["minutes"] .":".$value["seconds"];
            Return $t;

        } else {
            return (bool) FALSE;
        }
    }

    function get_test_data($courseware_id, $resource_id, $userid, $type='uid', $types)
    {
        if (!$courseware_id) {
            return false;
        }

        $test = Db::name('courseware_test')->where('courseware_id', '=', $courseware_id)->find();

        if (!$test) {
            return false;
        }

        if ($type == 'userid') {
            $userid = Db::name('members')->where('userid', '=', $userid)->value('id');
        }


        $data = [];
        $data['max_score'] = Db::name('test_submit')
            ->where('test_id', '=', $test['id'])
            ->where('userid', '=', $userid)
            ->where('resource_id', '=', $resource_id)
            ->where('type', '=', $types)
            ->max('score');
        $data['test_count'] = Db::name('test_submit')
            ->where('test_id', '=', $test['id'])
            ->where('userid', '=', $userid)
            ->where('resource_id', '=', $resource_id)
            ->where('type', '=', $types)
            ->count();
        if ($test['limits'] == 0) {
            $data['pass'] = '无分数限制';
        } else {
            $data['pass'] = $data['max_score'] >= $test['score'] ? '<font color="green">通过</font>':'<font color="red">未通过</font>';
        }

        $data['near_time'] = Db::name('test_submit')
            ->where('test_id', '=', $test['id'])
            ->where('userid', '=', $userid)
            ->where('resource_id', '=', $resource_id)
            ->where('type', '=', $types)
            ->order('id', 'desc')
            ->value('add_time');
        return $data;
    }

    /**
     * 获取测试排名
     * @date: 2019年9月17日
     * @author: Administrator
     * @return:
     */
    function get_test_rank($test_id, $resource_id, $type)
    {

        $list = Db::name('test_submit')
            ->field('id, userid, time, max(score) as score, add_time')
            ->where('test_id', '=', $test_id)
            ->where('resource_id', '=', $resource_id)
            ->where('type', '=', $type)
            ->group('userid')
            ->order(['score'=>'desc','time'=>'asc'])
            ->limit(20)
            ->select()
            ->toArray();

        if (!$list) {
            return [];
        }

        foreach ($list as $key => $value) {
            $list[$key] = Db::name('test_submit')
                ->where('test_id', '=', $test_id)
                ->where('resource_id', '=', $resource_id)
                ->where('type', '=', $type)
                ->where('userid', '=', $value['userid'])
                ->where('score', '=', $value['score'])
                ->order(['time'=>'asc'])
                ->find();
        }
        $last_score = array_column($list,'score');
        $last_names = array_column($list,'time');

        array_multisort($last_score,SORT_DESC,$last_names,SORT_ASC,$list);
        return $list;
    }

    /**
     * 将科学计数法的数字转换为正常的数字
     * 为了将数字处理完美一些，使用部分正则是可以接受的
     * @author loveyu
     * @param string $number
     * @return string
     */
    function convert_scientific_number_to_normal($number)
    {
        if(stripos($number, 'e') === false) {
            //判断是否为科学计数法
            return $number;
        }
        if(!preg_match(
            "/^([\\d.]+)[eE]([\\d\\-\\+]+)$/",
            str_replace(array(" ", ","), "", trim($number)), $matches)
        ) {
            //提取科学计数法中有效的数据，无法处理则直接返回
            return $number;
        }
        //对数字前后的0和点进行处理，防止数据干扰，实际上正确的科学计数法没有这个问题
        $data = preg_replace(array("/^[0]+/"), "", rtrim($matches[1], "0."));
        $length = (int)$matches[2];
        if($data[0] == ".") {
            //由于最前面的0可能被替换掉了，这里是小数要将0补齐
            $data = "0{$data}";
        }
        //这里有一种特殊可能，无需处理
        if($length == 0) {
            return $data;
        }
        //记住当前小数点的位置，用于判断左右移动
        $dot_position = strpos($data, ".");
        if($dot_position === false) {
            $dot_position = strlen($data);
        }
        //正式数据处理中，是不需要点号的，最后输出时会添加上去
        $data = str_replace(".", "", $data);
        if($length > 0) {
            //如果科学计数长度大于0
            //获取要添加0的个数，并在数据后面补充
            $repeat_length = $length - (strlen($data) - $dot_position);
            if($repeat_length > 0) {
                $data .= str_repeat('0', $repeat_length);
            }
            //小数点向后移n位
            $dot_position += $length;
            $data = ltrim(substr($data, 0, $dot_position), "0").".".substr($data, $dot_position);
        } elseif($length < 0) {
            //当前是一个负数
            //获取要重复的0的个数
            $repeat_length = abs($length) - $dot_position;
            if($repeat_length > 0) {
                //这里的值可能是小于0的数，由于小数点过长
                $data = str_repeat('0', $repeat_length).$data;
            }
            $dot_position += $length;//此处length为负数，直接操作
            if($dot_position < 1) {
                //补充数据处理，如果当前位置小于0则表示无需处理，直接补小数点即可
                $data = ".{$data}";
            } else {
                $data = substr($data, 0, $dot_position).".".substr($data, $dot_position);
            }
        }
        if($data[0] == ".") {
            //数据补0
            $data = "0{$data}";
        }
        return trim($data, ".");
    }